bitkeeper revision 1.1159.11.2 (41190460g_46PGXC611SAS9fnIgORA)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 10 Aug 2004 17:22:40 +0000 (17:22 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 10 Aug 2004 17:22:40 +0000 (17:22 +0000)
Fix CONFIG_HIGHMEM.

.rootkeys
linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig
linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile
linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c [new file with mode: 0644]
linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c
linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h [new file with mode: 0644]
linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h

index bdeeb555d1e25bc5fc5d0ee2dfa679ec70fba848..0de7d92f813ae9e24c535195cd6fbe746bac43d9 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.7-xen-sparse/arch/xen/i386/kernel/vsyscall.lds
 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile
 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c
+4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c
 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.7-xen-sparse/arch/xen/i386/mm/hypervisor.c
 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.7-xen-sparse/arch/xen/i386/mm/init.c
 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c
 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h
 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h
+4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h
 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/io.h
 40f5623am9BzluYFuV6EQfTd-so3dA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/do_timer.h
 40f5623adZQ1IZGPxbDXONjyZGYuTA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/io_ports.h
index 0cfb2d40a67201110170e05407e7061a5ee8b21a..1a051d436d23de710eb5955ad3a47dae6c8a4b10 100644 (file)
@@ -555,14 +555,14 @@ config HAVE_ARCH_BOOTMEM_NODE
        depends on NUMA
        default y
 
-config HIGHPTE
-       bool "Allocate 3rd-level pagetables from highmem"
-       depends on HIGHMEM4G || HIGHMEM64G
-       help
-         The VM uses one page table entry for each page of physical memory.
-         For systems with a lot of RAM, this can be wasteful of precious
-         low memory.  Setting this option will put user-space page table
-         entries in high memory.
+#config HIGHPTE
+#      bool "Allocate 3rd-level pagetables from highmem"
+#      depends on HIGHMEM4G || HIGHMEM64G
+#      help
+#        The VM uses one page table entry for each page of physical memory.
+#        For systems with a lot of RAM, this can be wasteful of precious
+#        low memory.  Setting this option will put user-space page table
+#        entries in high memory.
 
 #config MTRR
 #       bool "MTRR (Memory Type Range Register) support"
index a0f3470825c806381a3d102dc26804368464a679..55063591f02bbd7203a61c7bf27280eede0d55c1 100644 (file)
@@ -11,7 +11,7 @@ c-obj-y       := extable.o pageattr.o
 
 c-obj-$(CONFIG_DISCONTIGMEM)   += discontig.o
 c-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-c-obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_HIGHMEM) += highmem.o
 c-obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
 
 c-link :=
diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c
new file mode 100644 (file)
index 0000000..6b6fd16
--- /dev/null
@@ -0,0 +1,137 @@
+#include <linux/highmem.h>
+
+void *kmap(struct page *page)
+{
+       might_sleep();
+       if (page < highmem_start_page)
+               return page_address(page);
+       return kmap_high(page);
+}
+
+void kunmap(struct page *page)
+{
+       if (in_interrupt())
+               BUG();
+       if (page < highmem_start_page)
+               return;
+       kunmap_high(page);
+}
+
+/*
+ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+ * no global lock is needed and because the kmap code must perform a global TLB
+ * invalidation when the kmap pool wraps.
+ *
+ * However when holding an atomic kmap is is not legal to sleep, so atomic
+ * kmaps are appropriate for short, tight code paths only.
+ */
+void *kmap_atomic(struct page *page, enum km_type type)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+
+       /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+       inc_preempt_count();
+       if (page < highmem_start_page)
+               return page_address(page);
+
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       if (!pte_none(*(kmap_pte-idx)))
+               BUG();
+#endif
+       set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+       __flush_tlb_one(vaddr);
+
+       return (void*) vaddr;
+}
+
+/* Same as kmap_atomic but with PAGE_KERNEL_RO page protection */
+void *kmap_atomic_pte(struct page *page, enum km_type type)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+
+       /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+       inc_preempt_count();
+       if (page < highmem_start_page)
+               return page_address(page);
+
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       if (!pte_none(*(kmap_pte-idx)))
+               BUG();
+#endif
+       set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL_RO));
+       __flush_tlb_one(vaddr);
+
+       return (void*) vaddr;
+}
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#ifdef CONFIG_DEBUG_HIGHMEM
+       unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+       if (vaddr < FIXADDR_START) { // FIXME
+               dec_preempt_count();
+               preempt_check_resched();
+               return;
+       }
+
+       if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+               BUG();
+
+       /*
+        * force other mappings to Oops if they'll try to access
+        * this pte without first remap it
+        */
+       pte_clear(kmap_pte-idx);
+       __flush_tlb_one(vaddr);
+#endif
+
+       dec_preempt_count();
+       preempt_check_resched();
+}
+
+void kunmap_atomic_force(void *kvaddr, enum km_type type)
+{
+       unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+       if (vaddr < FIXADDR_START) { // FIXME
+               dec_preempt_count();
+               preempt_check_resched();
+               return;
+       }
+
+       if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+               BUG();
+
+       /*
+        * force other mappings to Oops if they'll try to access
+        * this pte without first remap it
+        */
+       pte_clear(kmap_pte-idx);
+       __flush_tlb_one(vaddr);
+
+       dec_preempt_count();
+       preempt_check_resched();
+}
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+       unsigned long idx, vaddr = (unsigned long)ptr;
+       pte_t *pte;
+
+       if (vaddr < FIXADDR_START)
+               return virt_to_page(ptr);
+
+       idx = virt_to_fix(vaddr);
+       pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+       return pte_page(*pte);
+}
+
index cbab491f2eee3f3e97d584a6fb85b8f52fb029ee..e9e70e61b09bfe850fc7c6e0cf725c7838f08c74 100644 (file)
@@ -194,9 +194,17 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
        pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
 #endif
        if (pte) {
+#ifdef CONFIG_HIGHPTE
+               void *kaddr = kmap_atomic(pte, KM_USER0);
+               clear_page(kaddr);
+               kunmap_atomic_force(kaddr, KM_USER0);
+#else
                clear_highpage(pte);
+#endif
+#ifdef CONFIG_HIGHPTE
+               if (pte < highmem_start_page)
+#endif
                __make_page_readonly(phys_to_virt(page_to_pseudophys(pte)));
-                               /* XXXcl highmem */
        }
        return pte;
 }
diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h
new file mode 100644 (file)
index 0000000..f608a13
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *                   Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with 
+ * up to 16 Terabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#include <asm/tlbflush.h>
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
+extern void kmap_init(void);
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+#if NR_CPUS <= 32
+#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23))
+#else
+#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23) - 0x200000UL)
+#endif
+#ifdef CONFIG_X86_PAE
+#define LAST_PKMAP 512
+#else
+#define LAST_PKMAP 1024
+#endif
+#define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+extern void * FASTCALL(kmap_high(struct page *page));
+extern void FASTCALL(kunmap_high(struct page *page));
+
+void *kmap(struct page *page);
+void kunmap(struct page *page);
+void *kmap_atomic(struct page *page, enum km_type type);
+void *kmap_atomic_pte(struct page *page, enum km_type type);
+void kunmap_atomic(void *kvaddr, enum km_type type);
+void kunmap_atomic_force(void *kvaddr, enum km_type type);
+struct page *kmap_atomic_to_page(void *ptr);
+
+#define flush_cache_kmaps()    do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
index be31d10f300157aac86fe0ac7e36abbc605a241b..8c8dfaa3dfa484c21f438459c06de675970e517b 100644 (file)
@@ -333,9 +333,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+       ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \
+        pte_index(address))
 #define pte_offset_map_nested(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+       ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + \
+        pte_index(address))
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else